package com.vipboot.platform.system.crud.service;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.github.yulichang.toolkit.JoinWrappers;
import com.github.yulichang.wrapper.MPJLambdaWrapper;
import com.vipboot.framework.core.constant.Const;
import com.vipboot.framework.core.util.MapStructUtil;
import com.vipboot.framework.core.util.StreamUtil;
import com.vipboot.framework.satoken.helper.LoginHelper;
import com.vipboot.platform.system.crud.dao.SysMenuDao;
import com.vipboot.platform.system.crud.dao.SysUserDao;
import com.vipboot.platform.system.domain.entity.*;
import com.vipboot.platform.system.domain.model.Router;
import com.vipboot.platform.system.domain.model.RouterMeta;
import com.vipboot.platform.system.domain.model.SysMenuDto;
import com.vipboot.platform.system.domain.vo.SysUserVo;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;


@RequiredArgsConstructor
@Slf4j
@Service
public class AuthSystemService {

    private final SysUserDao sysUserDao;
    private final SysMenuDao sysMenuDao;

    public SysUserVo getUserById(Long userId) {
        LambdaQueryWrapper<SysUser> lqw = Wrappers.lambdaQuery();
        lqw.eq(SysUser::getUserId, userId);
        return MapStructUtil.convert(sysUserDao.getOne(lqw), SysUserVo.class);
    }

    /**
     * 构建前端路由所需要的菜单
     *
     * @param menus 菜单列表
     * @return 路由列表
     */
    public List<Router> buildMenuRouters(List<SysMenuDto> menus) {
        List<Router> routers = new LinkedList<>();
        for (SysMenuDto menu : menus) {
            Router router = new Router();
//            String menuType = menu.getMenuType();
            router.setPath(menu.getPath());
            router.setName(menu.getRouterName());
            router.setComponent(menu.getComponent());

            RouterMeta meta = new RouterMeta();
            meta.setTitle(menu.getMenuName());
            meta.setIcon(menu.getIcon());
//            meta.setPerms(menu.getPerms());
//            meta.setIsHide(StrUtil.equals("1", menu.getIsHide()));
//            meta.setIsKeepAlive(StrUtil.equals("1", menu.getIsCache()));
//            meta.setIsKeepAlive(1 == menu.getIsCache());
            meta.setHidden(StrUtil.equals("1", menu.getVisible()));
            meta.setBreadcrumbHidden(StrUtil.equals("1", menu.getBreadcrumbHidden()));
            meta.setLevelHidden(StrUtil.equals("1", menu.getLevelHidden()));
            meta.setDynamicNewTab(StrUtil.equals("1", menu.getDynamicNewTab()));
            meta.setNoClosable(StrUtil.equals("1", menu.getNoClosable()));
            meta.setIsCustomSvg(StrUtil.equals("0", menu.getIsCustomSvg())); // 0自定义
            meta.setNoKeepAlive(1 == menu.getIsCache());
            meta.setActiveMenu("");
            meta.setTarget(menu.getTarget());

            router.setMeta(meta);
            List<SysMenuDto> cMenus = menu.getChildren();
            if (CollUtil.isNotEmpty(cMenus)) {
                router.setChildren(buildMenuRouters(cMenus));
            }
            routers.add(router);
        }
        return routers;
    }

    /**
     * 根据用户ID查询菜单
     *
     * @param userId 用户名称
     * @return 菜单列表
     */
    public List<SysMenuDto> listMenuTreeByUserId(Long userId) {
        if (LoginHelper.isSuperAdmin(userId)) {
            LambdaQueryWrapper<SysMenu> lqw = Wrappers.lambdaQuery();
            lqw.in(SysMenu::getMenuType, Const.MenuTypeDir, Const.MenuTypeMenu)
                    .eq(SysMenu::getStatus, Const.StatusNormal)
                    .orderByAsc(SysMenu::getParentId)
                    .orderByAsc(SysMenu::getSortNum);
            List<SysMenuDto> menus = sysMenuDao.listVo(lqw, SysMenuDto.class);
            return buildMenuTreeByParentId(menus);
        }

        /*select distinct m.menu_id, m.parent_id, m.menu_name, m.path, m.component, m.`query`, m.visible, m.status, ifnull(m.perms,'') as perms, m.is_frame, m.is_cache, m.menu_type, m.icon, m.order_num, m.create_time
            from SysMenuTable m
            left join sys_role_menu rm on m.menu_id = rm.menu_id
            left join sys_user_role ur on rm.role_id = ur.role_id
            left join sys_role ro on ur.role_id = ro.role_id
            left join sys_user u on ur.user_id = u.user_id
            where u.user_id = #{userId} and m.menu_type in ('M', 'C') and m.status = 0  AND ro.status = 0
            order by m.parent_id, m.order_num*/
        MPJLambdaWrapper<SysMenu> queryWrapper = JoinWrappers.lambda();
        queryWrapper.select(SysMenu::getMenuId, SysMenu::getParentId, SysMenu::getMenuName, SysMenu::getPath,
                SysMenu::getComponent, SysMenu::getQueryParam, SysMenu::getVisible, SysMenu::getStatus,
                SysMenu::getPerms, SysMenu::getIsFrame, SysMenu::getIsCache, SysMenu::getMenuType, SysMenu::getIcon,
                SysMenu::getSortNum, SysMenu::getCreateTime);
        queryWrapper.leftJoin(SysRoleMenu.class, SysRoleMenu::getMenuId, SysMenu::getMenuId)
                .leftJoin(SysUserRole.class, SysUserRole::getRoleId, SysRoleMenu::getRoleId)
                .leftJoin(SysRole.class, SysRole::getRoleId, SysUserRole::getRoleId)
                .eq(SysUserRole::getUserId, userId)
                .in(SysMenu::getMenuType, Const.MenuTypeDir, Const.MenuTypeMenu)
                .eq(SysRole::getStatus, Const.StatusNormal)
                .eq(SysMenu::getStatus, Const.StatusNormal)
                .orderByAsc(SysMenu::getParentId)
                .orderByAsc(SysMenu::getSortNum);
        List<SysMenuDto> menus = sysMenuDao.selectJoinList(SysMenuDto.class, queryWrapper);
        return buildMenuTreeByParentId(menus);

    }

    /**
     * 根据父节点的ID获取所有子节点
     *
     * @param list 分类表
     * @return String
     */
    private List<SysMenuDto> buildMenuTreeByParentId(List<SysMenuDto> list) {
        List<SysMenuDto> returnList = new ArrayList<>();
        for (SysMenuDto item : list) {
            // 一、根据传入的某个父节点ID,遍历该父节点的所有子节点
            if (item.getParentId() == 0) {
                recursionFn(list, item);
                returnList.add(item);
            }
        }
        return returnList;
    }

    /**
     * 递归列表
     */
    private void recursionFn(List<SysMenuDto> list, SysMenuDto item) {
        // 得到子节点列表
        List<SysMenuDto> childList = StreamUtil.filter(list, it -> it.getParentId().equals(item.getMenuId()));
        item.setChildren(childList);
        for (SysMenuDto itemChild : childList) {
            // 判断是否有子节点
            if (list.stream().anyMatch(it -> it.getParentId().equals(itemChild.getMenuId()))) {
                recursionFn(list, itemChild);
            }
        }
    }
}
